From 72d4a83af81ec86581fb5b9cee863f37ab677063 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Timm=20B=C3=A4der?= Date: Fri, 24 Jul 2020 08:49:24 +0200 Subject: [PATCH] gl renderer: Moar state tracking Track what we really need to send for inset shadows, which are used as a border replacement in many cases. Fishbowl says I can draw around 200-300 more switches per frame like this too. --- gsk/gl/gskglrenderer.c | 110 +++++++++-------- gsk/gl/gskglrenderops.c | 115 ++++++++++++++++++ gsk/gl/gskglrenderopsprivate.h | 26 ++++ gsk/gl/opbuffer.c | 2 +- gsk/gl/opbuffer.h | 27 ++-- gsk/resources/glsl/inset_shadow.glsl | 6 +- .../glsl/unblurred_outset_shadow.glsl | 1 + 7 files changed, 227 insertions(+), 60 deletions(-) diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 87774796ce..81b9302f6d 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -742,15 +742,9 @@ render_border_node (GskGLRenderer *self, gdk_rgba_equal (&colors[0], &colors[2]) && gdk_rgba_equal (&colors[0], &colors[3])) { - OpShadow *op; - ops_set_program (builder, &self->programs->inset_shadow_program); - op = ops_begin (builder, OP_CHANGE_INSET_SHADOW); - op->color = &colors[0]; - op->outline = transform_rect (self, builder, rounded_outline); - op->spread = widths[0]; - op->offset[0] = 0; - op->offset[1] = 0; + ops_set_inset_shadow (builder, transform_rect (self, builder, rounded_outline), + widths[0], &colors[0], 0, 0); load_vertex_data (ops_draw (builder, NULL), node, builder); return; @@ -1607,17 +1601,14 @@ render_unblurred_inset_shadow_node (GskGLRenderer *self, const float dx = gsk_inset_shadow_node_get_dx (node); const float dy = gsk_inset_shadow_node_get_dy (node); const float spread = gsk_inset_shadow_node_get_spread (node); - OpShadow *op; g_assert (blur_radius == 0); ops_set_program (builder, &self->programs->inset_shadow_program); - op = ops_begin (builder, OP_CHANGE_INSET_SHADOW); - op->color = gsk_inset_shadow_node_peek_color (node); - op->outline = transform_rect (self, builder, gsk_inset_shadow_node_peek_outline (node)); - op->spread = spread; - op->offset[0] = dx; - op->offset[1] = dy; + ops_set_inset_shadow (builder, transform_rect (self, builder, gsk_inset_shadow_node_peek_outline (node)), + spread, + gsk_inset_shadow_node_peek_color (node), + dx, dy); load_vertex_data (ops_draw (builder, NULL), node, builder); } @@ -1635,7 +1626,6 @@ render_inset_shadow_node (GskGLRenderer *self, const GskRoundedRect *node_outline = gsk_inset_shadow_node_peek_outline (node); float texture_width; float texture_height; - OpShadow *op; int blurred_texture_id; g_assert (blur_radius > 0); @@ -1699,12 +1689,10 @@ render_inset_shadow_node (GskGLRenderer *self, /* Actual inset shadow outline drawing */ ops_set_program (builder, &self->programs->inset_shadow_program); - op = ops_begin (builder, OP_CHANGE_INSET_SHADOW); - op->color = gsk_inset_shadow_node_peek_color (node); - op->outline = transform_rect (self, builder, &outline_to_blur); - op->spread = spread * scale; - op->offset[0] = dx * scale; - op->offset[1] = dy * scale; + ops_set_inset_shadow (builder, transform_rect (self, builder, &outline_to_blur), + spread * scale, + gsk_inset_shadow_node_peek_color (node), + dx * scale, dy * scale); ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) { { { 0, 0 }, { 0, 1 }, }, @@ -1772,15 +1760,12 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self, const float spread = gsk_outset_shadow_node_get_spread (node); const float dx = gsk_outset_shadow_node_get_dx (node); const float dy = gsk_outset_shadow_node_get_dy (node); - OpShadow *op; ops_set_program (builder, &self->programs->unblurred_outset_shadow_program); - op = ops_begin (builder, OP_CHANGE_UNBLURRED_OUTSET_SHADOW); - op->color = gsk_outset_shadow_node_peek_color (node); - op->outline = transform_rect (self, builder, outline); - op->spread = spread; - op->offset[0] = dx; - op->offset[1] = dy; + ops_set_unblurred_outset_shadow (builder, transform_rect (self, builder, outline), + spread, + gsk_outset_shadow_node_peek_color (node), + dx, dy); load_vertex_data (ops_draw (builder, NULL), node, builder); } @@ -1803,7 +1788,7 @@ render_outset_shadow_node (GskGLRenderer *self, const float dy = gsk_outset_shadow_node_get_dy (node); GskRoundedRect scaled_outline; int texture_width, texture_height; - OpShadow *shadow; + OpOutsetShadow *shadow; int blurred_texture_id; int cached_tid; bool do_slicing; @@ -1928,7 +1913,8 @@ render_outset_shadow_node (GskGLRenderer *self, ops_set_texture (builder, blurred_texture_id); shadow = ops_begin (builder, OP_CHANGE_OUTSET_SHADOW); - shadow->outline = transform_rect (self, builder, outline); + shadow->outline.value = transform_rect (self, builder, outline); + shadow->outline.send = TRUE; tx1 = 0; tx2 = 1; ty1 = 0; ty2 = 1; @@ -1956,7 +1942,8 @@ render_outset_shadow_node (GskGLRenderer *self, ops_set_texture (builder, blurred_texture_id); shadow = ops_begin (builder, OP_CHANGE_OUTSET_SHADOW); - shadow->outline = transform_rect (self, builder, outline); + shadow->outline.value = transform_rect (self, builder, outline); + shadow->outline.send = TRUE; { const float min_x = floorf (builder->dx + outline->bounds.origin.x - spread - (blur_extra / 2.0) + dx); @@ -2610,15 +2597,27 @@ apply_inset_shadow_op (const Program *program, const OpShadow *op) { OP_PRINT (" -> inset shadow. Color: %s, Offset: (%f, %f), Spread: %f, Outline: %s", - gdk_rgba_to_string (op->color), - op->offset[0], - op->offset[1], - op->spread, - gsk_rounded_rect_to_string (&op->outline)); - glUniform4fv (program->inset_shadow.color_location, 1, (float *)op->color); - glUniform2fv (program->inset_shadow.offset_location, 1, op->offset); - glUniform1f (program->inset_shadow.spread_location, op->spread); - glUniform4fv (program->inset_shadow.outline_rect_location, 3, (float *)&op->outline.bounds); + op->color.send ? gdk_rgba_to_string (op->color.value) : "don't send", + op->offset.send ? op->offset.value[0] : -1337.0, + op->offset.send ? op->offset.value[1] : -1337.0, + op->spread.send ? op->spread.value : -1337.0, + op->outline.send ? gsk_rounded_rect_to_string (&op->outline.value) : "don't send"); + if (op->outline.send) + { + if (op->outline.send_corners) + glUniform4fv (program->inset_shadow.outline_rect_location, 3, (float *)&op->outline.value); + else + glUniform4fv (program->inset_shadow.outline_rect_location, 1, (float *)&op->outline.value); + } + + if (op->color.send) + glUniform4fv (program->inset_shadow.color_location, 1, (float *)op->color.value); + + if (op->spread.send) + glUniform1f (program->inset_shadow.spread_location, op->spread.value); + + if (op->offset.send) + glUniform2fv (program->inset_shadow.offset_location, 1, op->offset.value); } static inline void @@ -2626,18 +2625,31 @@ apply_unblurred_outset_shadow_op (const Program *program, const OpShadow *op) { OP_PRINT (" -> unblurred outset shadow"); - glUniform4fv (program->unblurred_outset_shadow.color_location, 1, (float *)op->color); - glUniform2fv (program->unblurred_outset_shadow.offset_location, 1, op->offset); - glUniform1f (program->unblurred_outset_shadow.spread_location, op->spread); - glUniform4fv (program->unblurred_outset_shadow.outline_rect_location, 3, (float *)&op->outline.bounds); + + if (op->outline.send) + { + if (op->outline.send_corners) + glUniform4fv (program->unblurred_outset_shadow.outline_rect_location, 3, (float *)&op->outline.value); + else + glUniform4fv (program->unblurred_outset_shadow.outline_rect_location, 1, (float *)&op->outline.value); + } + + if (op->color.send) + glUniform4fv (program->unblurred_outset_shadow.color_location, 1, (float *)op->color.value); + + if (op->spread.send) + glUniform1f (program->unblurred_outset_shadow.spread_location, op->spread.value); + + if (op->offset.send) + glUniform2fv (program->unblurred_outset_shadow.offset_location, 1, op->offset.value); } static inline void -apply_outset_shadow_op (const Program *program, - const OpShadow *op) +apply_outset_shadow_op (const Program *program, + const OpOutsetShadow *op) { OP_PRINT (" -> outset shadow"); - glUniform4fv (program->outset_shadow.outline_rect_location, 3, (float *)&op->outline.bounds); + glUniform4fv (program->outset_shadow.outline_rect_location, 3, (float *)&op->outline.value.bounds); } static inline void @@ -2694,6 +2706,7 @@ static inline void apply_cross_fade_op (const Program *program, const OpCrossFade *op) { + OP_PRINT (" -> Cross fade"); /* End texture id */ glUniform1i (program->cross_fade.source2_location, 1); glActiveTexture (GL_TEXTURE0 + 1); @@ -3505,6 +3518,7 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self) break; case OP_CLEAR: + OP_PRINT ("-> CLEAR"); glClearColor (0, 0, 0, 0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); break; diff --git a/gsk/gl/gskglrenderops.c b/gsk/gl/gskglrenderops.c index c6bc5b4de8..f710041cef 100644 --- a/gsk/gl/gskglrenderops.c +++ b/gsk/gl/gskglrenderops.c @@ -747,3 +747,118 @@ ops_get_buffer (RenderOpBuilder *builder) { return &builder->render_ops; } + +void +ops_set_inset_shadow (RenderOpBuilder *self, + const GskRoundedRect outline, + float spread, + const GdkRGBA *color, + float dx, + float dy) +{ + ProgramState *current_program_state = get_current_program_state (self); + OpShadow *op; + + op = ops_begin (self, OP_CHANGE_INSET_SHADOW); + + if (!rounded_rect_equal (&outline, ¤t_program_state->inset_shadow.outline)) + { + op->outline.value = outline; + op->outline.send = TRUE; + op->outline.send_corners = !rounded_rect_corners_equal (¤t_program_state->inset_shadow.outline, + &outline); + current_program_state->inset_shadow.outline = outline; + } + else + op->outline.send = FALSE; + + if (spread != current_program_state->inset_shadow.spread) + { + op->spread.value = spread; + op->spread.send = TRUE; + + current_program_state->inset_shadow.spread = spread; + } + else + op->spread.send = FALSE; + + if (!gdk_rgba_equal (color, ¤t_program_state->inset_shadow.color)) + { + op->color.value = color; + op->color.send = TRUE; + + current_program_state->inset_shadow.color = *color; + } + else + op->color.send = FALSE; + + if (dx != current_program_state->inset_shadow.dx || + dy != current_program_state->inset_shadow.dy) + { + op->offset.value[0] = dx; + op->offset.value[1] = dy; + op->offset.send = TRUE; + + current_program_state->inset_shadow.dx = dx; + current_program_state->inset_shadow.dy = dy; + } + else + op->offset.send = FALSE; +} +void +ops_set_unblurred_outset_shadow (RenderOpBuilder *self, + const GskRoundedRect outline, + float spread, + const GdkRGBA *color, + float dx, + float dy) +{ + ProgramState *current_program_state = get_current_program_state (self); + OpShadow *op; + + op = ops_begin (self, OP_CHANGE_UNBLURRED_OUTSET_SHADOW); + + if (!rounded_rect_equal (&outline, ¤t_program_state->unblurred_outset_shadow.outline)) + { + op->outline.value = outline; + op->outline.send = TRUE; + op->outline.send_corners = !rounded_rect_corners_equal (¤t_program_state->unblurred_outset_shadow.outline, + &outline); + current_program_state->unblurred_outset_shadow.outline = outline; + } + else + op->outline.send = FALSE; + + if (spread != current_program_state->unblurred_outset_shadow.spread) + { + op->spread.value = spread; + op->spread.send = TRUE; + + current_program_state->unblurred_outset_shadow.spread = spread; + } + else + op->spread.send = FALSE; + + if (!gdk_rgba_equal (color, ¤t_program_state->unblurred_outset_shadow.color)) + { + op->color.value = color; + op->color.send = TRUE; + + current_program_state->unblurred_outset_shadow.color = *color; + } + else + op->color.send = FALSE; + + if (dx != current_program_state->unblurred_outset_shadow.dx || + dy != current_program_state->unblurred_outset_shadow.dy) + { + op->offset.value[0] = dx; + op->offset.value[1] = dy; + op->offset.send = TRUE; + + current_program_state->unblurred_outset_shadow.dx = dx; + current_program_state->unblurred_outset_shadow.dy = dy; + } + else + op->offset.send = FALSE; +} diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h index 2ddc048dba..0a8bf557f9 100644 --- a/gsk/gl/gskglrenderopsprivate.h +++ b/gsk/gl/gskglrenderopsprivate.h @@ -122,6 +122,20 @@ typedef struct GdkRGBA color; GskRoundedRect outline; } border; + struct { + GskRoundedRect outline; + float dx; + float dy; + float spread; + GdkRGBA color; + } inset_shadow; + struct { + GskRoundedRect outline; + float dx; + float dy; + float spread; + GdkRGBA color; + } unblurred_outset_shadow; }; } ProgramState; @@ -237,6 +251,18 @@ void ops_set_border_width (RenderOpBuilder *builder, void ops_set_border_color (RenderOpBuilder *builder, const GdkRGBA *color); +void ops_set_inset_shadow (RenderOpBuilder *self, + const GskRoundedRect outline, + float spread, + const GdkRGBA *color, + float dx, + float dy); +void ops_set_unblurred_outset_shadow (RenderOpBuilder *self, + const GskRoundedRect outline, + float spread, + const GdkRGBA *color, + float dx, + float dy); GskQuadVertex * ops_draw (RenderOpBuilder *builder, const GskQuadVertex vertex_data[GL_N_VERTICES]); diff --git a/gsk/gl/opbuffer.c b/gsk/gl/opbuffer.c index b85127b5dd..496308c5ae 100644 --- a/gsk/gl/opbuffer.c +++ b/gsk/gl/opbuffer.c @@ -18,7 +18,7 @@ static guint op_sizes[OP_LAST] = { sizeof (OpColorMatrix), sizeof (OpBlur), sizeof (OpShadow), - sizeof (OpShadow), + sizeof (OpOutsetShadow), sizeof (OpBorder), sizeof (OpBorder), sizeof (OpBorder), diff --git a/gsk/gl/opbuffer.h b/gsk/gl/opbuffer.h index 4c33babf97..76609c82a1 100644 --- a/gsk/gl/opbuffer.h +++ b/gsk/gl/opbuffer.h @@ -41,11 +41,30 @@ typedef enum OP_LAST } OpKind; + +typedef struct { float value; guint send: 1; } FloatUniformValue; +typedef struct { float value[2]; guint send: 1; } Float2UniformValue; +typedef struct { GskRoundedRect value; guint send: 1; guint send_corners: 1; } RRUniformValue; +typedef struct { const GdkRGBA *value; guint send: 1; } RGBAUniformValue; + /* OpNode are allocated within OpBuffer.pos, but we keep * a secondary index into the locations of that buffer * from OpBuffer.index. This allows peeking at the kind * and quickly replacing existing entries when necessary. */ +typedef struct +{ + RRUniformValue outline; + FloatUniformValue spread; + Float2UniformValue offset; + RGBAUniformValue color; +} OpShadow; + +typedef struct +{ + RRUniformValue outline; +} OpOutsetShadow; + typedef struct { guint pos; @@ -128,14 +147,6 @@ typedef struct float dir[2]; } OpBlur; -typedef struct -{ - GskRoundedRect outline; - float spread; - float offset[2]; - const GdkRGBA *color; -} OpShadow; - typedef struct { float widths[4]; diff --git a/gsk/resources/glsl/inset_shadow.glsl b/gsk/resources/glsl/inset_shadow.glsl index 238540c731..5b43779fe8 100644 --- a/gsk/resources/glsl/inset_shadow.glsl +++ b/gsk/resources/glsl/inset_shadow.glsl @@ -35,9 +35,9 @@ _IN_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline; void main() { vec2 frag = get_frag_coord(); - float alpha = clamp (rounded_rect_coverage(decode_rect(transformed_outside_outline), frag) - - rounded_rect_coverage(decode_rect(transformed_inside_outline), frag), - 0.0, 1.0); + float alpha = clamp(rounded_rect_coverage(decode_rect(transformed_outside_outline), frag) - + rounded_rect_coverage(decode_rect(transformed_inside_outline), frag), + 0.0, 1.0); setOutputColor(final_color * alpha); } diff --git a/gsk/resources/glsl/unblurred_outset_shadow.glsl b/gsk/resources/glsl/unblurred_outset_shadow.glsl index 419605e092..a789155b64 100644 --- a/gsk/resources/glsl/unblurred_outset_shadow.glsl +++ b/gsk/resources/glsl/unblurred_outset_shadow.glsl @@ -41,3 +41,4 @@ void main() { setOutputColor(final_color * alpha); } + -- 2.30.2